package com.zenithmind.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.common.result.PageResult;
import com.zenithmind.user.mapper.EmailLogMapper;
import com.zenithmind.user.pojo.domain.EmailLog;
import com.zenithmind.user.pojo.dto.EmailRequestDTO;
import com.zenithmind.user.pojo.query.EmailLogQuery;
import com.zenithmind.user.pojo.vo.EmailLogVO;
import com.zenithmind.user.service.EmailService;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import jakarta.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import com.zenithmind.common.annotation.DataCache;
import com.zenithmind.common.annotation.DataCacheEvict;

/**
 * 邮件服务实现
 */
@Slf4j
@Service
public class EmailServiceImpl extends ServiceImpl<EmailLogMapper, EmailLog> implements EmailService {

    @Autowired
    private JavaMailSender mailSender;

    @Autowired
    private EmailLogMapper emailLogMapper;

    @Value("${spring.mail.username}")
    private String sender;

    @Override
    @DataCacheEvict(prefix = "email:log", allEntries = true)
    public EmailLog sendSimpleEmail(EmailRequestDTO emailRequestDTO) {
        return sendSimpleEmail(emailRequestDTO.getTo(), emailRequestDTO.getSubject(), emailRequestDTO.getContent());
    }

    @Override
    @DataCacheEvict(prefix = "email:log", allEntries = true)
    public EmailLog sendSimpleEmail(String to, String subject, String content) {
        EmailLog emailLog = new EmailLog();
        emailLog.setToEmail(to);
        emailLog.setSubject(subject);
        emailLog.setContentType(0); // 文本
        emailLog.setContentSummary(content.length() > 100 ? content.substring(0, 100) + "..." : content);
        emailLog.setEmailType(0); // 普通邮件
        emailLog.setSendTime(LocalDateTime.now());

        try {
            SimpleMailMessage message = new SimpleMailMessage();
            message.setFrom(sender);
            message.setTo(to);
            message.setSubject(subject);
            message.setText(content);
            mailSender.send(message);

            emailLog.setStatus(1); // 成功
            log.info("发送简单邮件成功: {}", to);
        } catch (Exception e) {
            emailLog.setStatus(0); // 失败
            emailLog.setFailReason(e.getMessage());
            log.error("发送简单邮件失败: {}", e.getMessage());
        }

        // 保存邮件日志
        emailLogMapper.insert(emailLog);
        return emailLog;
    }

    @Override
    @DataCacheEvict(prefix = "email:log", allEntries = true)
    public EmailLog sendHtmlEmail(EmailRequestDTO emailRequestDTO) {
        return sendHtmlEmail(emailRequestDTO.getTo(), emailRequestDTO.getSubject(), emailRequestDTO.getHtmlContent());
    }

    @Override
    @DataCacheEvict(prefix = "email:log", allEntries = true)
    public EmailLog sendHtmlEmail(String to, String subject, String htmlContent) {
        EmailLog emailLog = new EmailLog();
        emailLog.setToEmail(to);
        emailLog.setSubject(subject);
        emailLog.setContentType(1); // HTML
        emailLog.setContentSummary(htmlContent.replaceAll("<[^>]*>", ""));
        emailLog.setContentSummary(
                emailLog.getContentSummary().length() > 100 ? emailLog.getContentSummary().substring(0, 100) + "..."
                        : emailLog.getContentSummary());
        emailLog.setEmailType(0); // 普通邮件
        emailLog.setSendTime(LocalDateTime.now());

        try {
            MimeMessage message = mailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
            helper.setFrom(sender);
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(htmlContent, true);
            mailSender.send(message);

            emailLog.setStatus(1); // 成功
            log.info("发送HTML邮件成功: {}", to);
        } catch (MessagingException e) {
            emailLog.setStatus(0); // 失败
            emailLog.setFailReason(e.getMessage());
            log.error("发送HTML邮件失败: {}", e.getMessage());
        }

        // 保存邮件日志
        emailLogMapper.insert(emailLog);
        return emailLog;
    }

    /**
     * 发送验证码邮件
     *
     * @param to   收件人邮箱地址
     * @param code 验证码字符串
     * @param type 验证码类型
     */
    @Override
    @DataCacheEvict(prefix = "email:log", allEntries = true)
    public EmailLog sendVerificationCode(String to, String code, int type) {
        // 根据类型选择不同的邮件主题和内容
        String subject;
        String htmlContent;
        String operationType;
        
        switch(type) {
            case 1: // 注册验证码
                subject = "ZenithMind - 注册验证码";
                operationType = "注册账号";
                break;
            case 2: // 重置密码验证码
                subject = "ZenithMind - 重置密码验证码";
                operationType = "重置密码";
                break;
            case 0: // 登录验证码
            default:
                subject = "ZenithMind - 登录验证码";
                operationType = "登录系统";
                break;
        }
        
        // 构建通用邮件模板
        htmlContent = "<div style='max-width:600px;margin:0 auto;font-family:Arial,sans-serif;'>"
                + "<div style='background:#4a6cf7;padding:20px;color:white;text-align:center;'>"
                + "<h2>ZenithMind 验证码</h2>"
                + "</div>"
                + "<div style='padding:20px;background:#f9f9f9;'>"
                + "<p>尊敬的用户：</p>"
                + "<p>您正在" + operationType + "，您的验证码是：</p>"
                + "<div style='background:#eee;font-size:24px;font-weight:bold;text-align:center;padding:15px;letter-spacing:5px;margin:20px 0;border-radius:4px;'>"
                + code + "</div>"
                + "<p>该验证码5分钟内有效，请勿泄露给他人。</p>"
                + "<p>如非本人操作，请忽略此邮件。</p>"
                + "</div>"
                + "<div style='padding:15px;text-align:center;font-size:12px;color:#666;background:#eee;'>"
                + "<p>© " + java.time.Year.now().getValue() + " ZenithMind. 保留所有权利。</p>"
                + "</div>"
                + "</div>";

        EmailLog emailLog = new EmailLog();
        emailLog.setToEmail(to);
        emailLog.setSubject(subject);
        emailLog.setContentType(1); // HTML
        emailLog.setContentSummary("验证码邮件: " + code);
        emailLog.setEmailType(1); // 验证码
        emailLog.setSendTime(LocalDateTime.now());

        try {
            MimeMessage message = mailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
            helper.setFrom(sender);
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(htmlContent, true);
            mailSender.send(message);

            emailLog.setStatus(1); // 成功
            log.info("发送验证码邮件成功: {}", to);
        } catch (MessagingException e) {
            emailLog.setStatus(0); // 失败
            emailLog.setFailReason(e.getMessage());
            log.error("发送验证码邮件失败: {}", e.getMessage());
        }

        // 保存邮件日志
        emailLogMapper.insert(emailLog);
        return emailLog;
    }

    /**
     * 发送验证码邮件 (默认为登录验证码)
     *
     * @param to   收件人邮箱地址
     * @param code 验证码字符串
     */
    @Override
    @DataCacheEvict(prefix = "email:log", allEntries = true)
    public EmailLog sendVerificationCode(String to, String code) {
        return sendVerificationCode(to, code, 0); // 默认为登录验证码
    }

    @Override
    @DataCache(prefix = "email:history", key = "#email + ':' + #limit")
    public List<EmailLog> getEmailHistory(EmailRequestDTO emailRequestDTO) {
        return getEmailHistory(emailRequestDTO.getTo(), emailRequestDTO.getLimit());
    }

    @Override
    @DataCache(prefix = "email:history", key = "#email + ':' + #limit")
    public List<EmailLog> getEmailHistory(String email, int limit) {
        LambdaQueryWrapper<EmailLog> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(EmailLog::getToEmail, email)
                .orderByDesc(EmailLog::getSendTime)
                .last("LIMIT " + limit);
        return emailLogMapper.selectList(queryWrapper);
    }

    /**
     * 获取客户端IP地址
     *
     * @param request HTTP请求
     * @return IP地址
     */
    public String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    /**
     * 对邮箱进行掩码处理
     *
     * @param email 原始邮箱
     * @return 掩码后的邮箱
     */
    public String maskEmail(String email) {
        if (email == null || email.length() < 5 || !email.contains("@")) {
            return "invalid-email";
        }

        int atIndex = email.indexOf('@');
        int length = atIndex;
        String prefix = length <= 3 ? email.substring(0, 1) : email.substring(0, 3);
        String suffix = email.substring(atIndex);

        StringBuilder masked = new StringBuilder(prefix);
        for (int i = 0; i < length - prefix.length(); i++) {
            masked.append('*');
        }
        masked.append(suffix);

        return masked.toString();
    }

    /**
     * 设置请求DTO的IP地址
     *
     * @param emailRequestDTO 邮件请求DTO
     * @param request         HTTP请求
     */
    public void setRequestIpAddress(EmailRequestDTO emailRequestDTO, HttpServletRequest request) {
        emailRequestDTO.setIpAddress(getClientIp(request));
    }

    /**
     * 发送简单文本邮件（带请求对象）
     *
     * @param emailRequestDTO 邮件请求DTO
     * @param request         HTTP请求
     * @return 邮件日志记录
     */
    @DataCacheEvict(prefix = "email:log", allEntries = true)
    public EmailLog sendSimpleEmail(EmailRequestDTO emailRequestDTO, HttpServletRequest request) {
        // 设置IP地址
        setRequestIpAddress(emailRequestDTO, request);
        return sendSimpleEmail(emailRequestDTO);
    }

    /**
     * 发送HTML邮件（带请求对象）
     *
     * @param emailRequestDTO 邮件请求DTO
     * @param request         HTTP请求
     * @return 邮件日志记录
     */
    @DataCacheEvict(prefix = "email:log", allEntries = true)
    public EmailLog sendHtmlEmail(EmailRequestDTO emailRequestDTO, HttpServletRequest request) {
        // 设置IP地址
        setRequestIpAddress(emailRequestDTO, request);
        return sendHtmlEmail(emailRequestDTO);
    }

    /**
     * 分页查询邮件记录
     *
     * @param emailLogQuery 邮件查询条件，包含分页信息和查询条件
     * @return 分页邮件记录
     */
    @Override
    @DataCache(prefix = "email:page", key = "#emailLogQuery.toString()")
    public PageResult<EmailLogVO> pageEmailLogs(EmailLogQuery emailLogQuery) {
        // 创建分页对象
        Page<EmailLog> page = emailLogQuery.toPage();

        // 执行分页查询
        Page<EmailLog> result = lambdaQuery()
        .like(StringUtils.isNotBlank(emailLogQuery.getEmail()), EmailLog::getToEmail, emailLogQuery.getEmail())
        .eq(emailLogQuery.getStatus() != null, EmailLog::getStatus, emailLogQuery.getStatus())
        .orderByDesc(EmailLog::getSendTime)
        .page(page);

        // 将结果转换为VO对象   
        List<EmailLogVO> voList = result.getRecords().stream()
        .map(this::convertToEmailLogVO)
        .collect(Collectors.toList());

        // 构造返回结果
        return new PageResult<>(
                voList,
                result.getTotal(),
                result.getCurrent(),
                result.getSize());
    }

    /**
     * 将EmailLog实体转换为EmailLogVO
     *
     * @param emailLog 邮件日志实体
     * @return 邮件日志VO
     */
    private EmailLogVO convertToEmailLogVO(EmailLog emailLog) {
        EmailLogVO emailLogVO = new EmailLogVO();
        BeanUtils.copyProperties(emailLog, emailLogVO);
        return emailLogVO;
    }

    /**
     * 统计邮件发送情况
     *
     * @return 统计数据
     */
    @Override
    @DataCache(prefix = "email:stats", expireTime = 1800) // 30分钟缓存过期
    public Map<String, Object> getEmailStatistics() {
        Map<String, Object> statistics = new HashMap<>();

        // 统计总邮件数
        long totalCount = count();
        statistics.put("totalCount", totalCount);

        // 统计成功发送数
        LambdaQueryWrapper<EmailLog> successWrapper = new LambdaQueryWrapper<>();
        successWrapper.eq(EmailLog::getStatus, 1);
        long successCount = count(successWrapper);
        statistics.put("successCount", successCount);

        // 统计失败发送数
        LambdaQueryWrapper<EmailLog> failedWrapper = new LambdaQueryWrapper<>();
        failedWrapper.eq(EmailLog::getStatus, 0);
        long failedCount = count(failedWrapper);
        statistics.put("failedCount", failedCount);

        // 计算成功率
        double successRate = totalCount > 0 ? (double) successCount / totalCount * 100 : 0;
        statistics.put("successRate", Math.round(successRate * 100) / 100.0);

        // 统计不同类型邮件
        Map<Integer, Long> typeCountMap = new HashMap<>();
        LambdaQueryWrapper<EmailLog> typeWrapper = new LambdaQueryWrapper<>();
        typeWrapper.select(EmailLog::getEmailType)
                  .groupBy(EmailLog::getEmailType);
        List<Map<String, Object>> typeCounts = listMaps(typeWrapper);

        for (Map<String, Object> item : typeCounts) {
            Integer type = null;
            Object typeObj = item.get("email_type");
            
            if (typeObj instanceof Boolean) {
                type = (Boolean) typeObj ? 1 : 0;
            } else if (typeObj instanceof Integer) {
                type = (Integer) typeObj;
            } else if (typeObj instanceof Long) {
                type = ((Long) typeObj).intValue();
            }
            
            if (type != null) {
                // 使用 count 查询获取每种类型的数量
                LambdaQueryWrapper<EmailLog> countWrapper = new LambdaQueryWrapper<>();
                countWrapper.eq(EmailLog::getEmailType, type);
                long count = count(countWrapper);
                typeCountMap.put(type, count);
            }
        }
        statistics.put("typeDistribution", typeCountMap);

        // 今日发送统计
        LocalDateTime today = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0);
        LambdaQueryWrapper<EmailLog> todayWrapper = new LambdaQueryWrapper<>();
        todayWrapper.ge(EmailLog::getSendTime, today);
        long todayCount = count(todayWrapper);
        statistics.put("todayCount", todayCount);

        return statistics;
    }
}